package com.njupt.yanglonglong.report.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njupt.yanglonglong.report.demo.common.Result;
import com.njupt.yanglonglong.report.demo.config.minio.MinioProperties;
import com.njupt.yanglonglong.report.demo.dto.StudentGradeDto;
import com.njupt.yanglonglong.report.demo.dto.StudentsGradeDto;
import com.njupt.yanglonglong.report.demo.entity.RUser;
import com.njupt.yanglonglong.report.demo.entity.Report;
import com.njupt.yanglonglong.report.demo.entity.ScoreVO;
import com.njupt.yanglonglong.report.demo.mapper.RAppliedStudentMapper;
import com.njupt.yanglonglong.report.demo.service.ReportService;
import com.njupt.yanglonglong.report.demo.utils.MinIoUtil;
import com.njupt.yanglonglong.report.demo.utils.RedisUtil;
import com.njupt.yanglonglong.report.demo.utils.StringParseUtil;
import com.njupt.yanglonglong.report.demo.utils.TimeUtil;
import com.njupt.yanglonglong.report.demo.vo.ReportInfo;
import com.njupt.yanglonglong.report.demo.vo.ReportVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @className: ReportController
 * @Description: 查询文件位置等
 * @author: lpl
 * @date: 2021/4/26 17:45
 */
@RestController
@CrossOrigin
@Slf4j
public class ReportController {

    @Autowired
    private ReportService reportService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private MinioProperties minioProperties;

    @Autowired
    private RAppliedStudentMapper studentMapper;

    /**
     * 教师获取已提交的报告
     *
     * @param map 实验ID
     * @return isSuccess
     */
    @PostMapping("/getCommittedReportListByExperId")
    public Result getCommittedReportListByExperId(@RequestBody HashMap<String, String> map) {
        JSONObject res = new JSONObject();
        String experId = map.get("experId");
        List<ReportVO> reports = null;
        try {
            reports = reportService.getCommittedReportListByExperId(experId);
        } catch (Exception e) {
            e.printStackTrace();
            res.put("msg", "获取报告列表出错");
            return Result.error(res);
        }
        res.put("msg", "获取报告列表成功");
        res.put("reports", reports);
        return Result.success(res);
    }

    @PostMapping("/getReportListByExperId")
    public Result getReportListByExperId(@RequestBody HashMap<String, String> map) {
        JSONObject res = new JSONObject();
        String experId = map.get("experId");
        List<ReportVO> reports = null;
        try {
            reports = reportService.getCommittedReportListByExperId(experId);
        } catch (Exception e) {
            e.printStackTrace();
            res.put("msg", "获取报告列表出错");
            return Result.error(res);
        }
        res.put("msg", "获取报告列表成功");
        res.put("reports", reports);
        return Result.success(res);
    }

    /**
     * 上传预习文件到服务器，并更改url
     *
     * @param request stuId
     * @param experId exper_id
     * @param file    文件
     * @return isSuccess
     */
    @RequestMapping("/uploadPreview")
    public Result<JSONObject> uploadPreview(HttpServletRequest request, String experId, MultipartFile file) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            res.put("msg", "用户权限校验失败，请先登录");
            return Result.error(res);
        }
        log.info("/uploadPreview收到: user{} , experId={}", user, experId);
        String stuId = user.getUserId();
        //查找记录是否已存在
        Report report = reportService.getReportByStudentIdExperimentId(stuId, experId);
        if (report == null) {
            report = new Report();
            report.setStuId(stuId);
            report.setExperId(experId);
            report.setStatus(2);
        } else {
            //删除minio服务器中的文件
            try {
                String previewFile = report.getPreviewFile();
                if (previewFile != null) {
                    String fileName = StringParseUtil.getFileNameFromUrl(previewFile);
                    MinIoUtil.deleteFile(minioProperties.getBucketName(), fileName);
                    log.info("【minIO删除文件：" + fileName + "成功】");
                }
            } catch (UnsupportedEncodingException e) {
                log.error(Arrays.toString(e.getStackTrace()));
            }
        }
        String fileUrl = MinIoUtil.upload(minioProperties.getBucketName(), file, user.getUserId());
        log.info("[文件url]" + fileUrl);
        report.setPreviewFile(fileUrl);
        report.setPreviewTime(TimeUtil.format(new Date()));

        QueryWrapper<Report> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stu_id", stuId).eq("exper_id", experId);
        boolean saveOrUpdate = reportService.saveOrUpdate(report, queryWrapper);
        if (!saveOrUpdate) {
            log.error("/uploadPreview上传文件或更改文件url失败");
            res.put("msg", "上传失败");
            return Result.error(res);
        }
        res.put("msg", "上传预习报告成功");
        return Result.success(res);
    }

    /**
     * 上传验收
     *
     * @param request 用户
     * @param experId 实验id
     * @param file    文件
     * @return isSuccess
     */
    @RequestMapping("/uploadAcceptance")
    public Result<JSONObject> uploadAcceptance(HttpServletRequest request, String experId, MultipartFile file) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            res.put("msg", "用户权限校验失败，请先登录");
            return Result.error(res);
        }
        log.info("/uploadAcceptance收到: user{} , experId={}", user, experId);
        String stuId = user.getUserId();
        //查找记录是否已存在
        Report report = reportService.getReportByStudentIdExperimentId(stuId, experId);
        if (report == null) {
            report = new Report();
            report.setStuId(stuId);
            report.setExperId(experId);
            report.setStatus(2);
        } else {
            //删除minio服务器中的文件
            try {
                String acceptanceFile = report.getAcceptanceFile();
                if (acceptanceFile != null) {
                    String fileName = StringParseUtil.getFileNameFromUrl(acceptanceFile);
                    MinIoUtil.deleteFile(minioProperties.getBucketName(), fileName);
                    log.info("【minIO删除文件：" + fileName + "成功】");
                }
            } catch (UnsupportedEncodingException e) {
                log.error(Arrays.toString(e.getStackTrace()));
            }
        }
        String fileUrl = MinIoUtil.upload(minioProperties.getBucketName(), file, user.getUserId());
        log.info("[文件url]" + fileUrl);
        report.setAcceptanceFile(fileUrl);
        report.setAcceptanceTime(TimeUtil.format(new Date()));
        QueryWrapper<Report> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stu_id", stuId).eq("exper_id", experId);
        boolean saveOrUpdate = reportService.saveOrUpdate(report, queryWrapper);
        if (!saveOrUpdate) {
            log.error("/uploadAcceptance上传文件或更改文件url失败");
            res.put("msg", "上传失败");
            return Result.error(res);
        }
        res.put("msg", "上传验收报告成功");
        return Result.success(res);
    }

    /**
     * 上传报告
     *
     * @param request 用户
     * @param experId 实验id
     * @param file    文件
     * @return isSuccess
     */
    @RequestMapping("/uploadReport")
    public Result<JSONObject> uploadReport(HttpServletRequest request, String experId, MultipartFile file) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            res.put("msg", "用户权限校验失败，请先登录");
            return Result.error(res);
        }
        log.info("/uploadReport收到: user{} , experId={}", user, experId);
        String stuId = user.getUserId();
        //查找记录是否已存在
        Report report = reportService.getReportByStudentIdExperimentId(stuId, experId);
        if (report == null) {
            report = new Report();
            report.setStuId(stuId);
            report.setExperId(experId);
            report.setStatus(2);
        } else {
            //删除minio服务器中的文件
            try {
                String acceptanceFile = report.getReportFile();
                if (acceptanceFile != null) {
                    String fileName = StringParseUtil.getFileNameFromUrl(acceptanceFile);
                    MinIoUtil.deleteFile(minioProperties.getBucketName(), fileName);
                    log.info("【minIO删除文件：" + fileName + "成功】");
                }
            } catch (UnsupportedEncodingException e) {
                log.error(Arrays.toString(e.getStackTrace()));
            }
        }
        String fileUrl = MinIoUtil.upload(minioProperties.getBucketName(), file, user.getUserId());
        log.info("[文件url]" + fileUrl);
        report.setReportFile(fileUrl);
        report.setReportTime(TimeUtil.format(new Date()));
        QueryWrapper<Report> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stu_id", stuId).eq("exper_id", experId);
        boolean saveOrUpdate = reportService.saveOrUpdate(report, queryWrapper);
        if (!saveOrUpdate) {
            log.error("/uploadReport上传文件或更改文件url失败");
            res.put("msg", "上传失败");
            return Result.error(res);
        }
        res.put("msg", "上传实验报告成功");
        return Result.success(res);
    }

    /**
     * 通过老师ID和课程ID查询成绩
     * todo 前端对接
     *
     * @param request 用户ID
     * @param map     课程ID
     * @return 成绩结果
     */
    @PostMapping("/queryAllStuGrade")
    public Result<JSONObject> queryAllStuGrade(HttpServletRequest request, @RequestBody HashMap<String, String> map) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            res.put("msg", "用户出错");
            return Result.error(res);
        }
        log.info("/queryAllStuGrade接到请求 user:{} , data:{}", user, map);
        String courseId = map.get("courseId");
        if (courseId == null) {
            res.put("msg", "获取参数错误");
            log.error("/queryAllStuGrade没有提取出courseId");
            return Result.error(res);
        }
        String teacherId = user.getUserId();
        //查询
        List<StudentsGradeDto> studentsGradeDtos = reportService.queryGradeByTeacherCourseId(teacherId, courseId);
        if (studentsGradeDtos == null) {
            log.error("/queryAllStuGrade查询结果为空，user:{} data:{}", user, map);
            res.put("msg", "您好像没有选课的学生");
            return Result.success(res);
        }
        log.info("/queryAllStuGrade查询结果为，res:{}", studentsGradeDtos);
        res.put("data", studentsGradeDtos);
        return Result.success(res);
    }

    /**
     * 学生端查询自己本课程的成绩
     * todo 前端对接
     *
     * @param request 用户Id
     * @param map     课程ID
     * @return
     */
    @PostMapping("/queryStuGrades")
    public Result<JSONObject> queryStuGrades(HttpServletRequest request, @RequestBody HashMap<String, String> map) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            res.put("msg", "获取用户出错");
            return Result.error(res);
        }
        log.info("/queryStuGrades接到请求 user:{} , data:{}", user, map);
        String courseId = map.get("courseId");
        if (courseId == null) {
            res.put("msg", "获取参数错误");
            log.error("/queryStuGrades没有提取出courseId");
            return Result.error(res);
        }
        String studentId = user.getUserId();
        List<StudentGradeDto> studentGradeDtos = reportService.queryStudentGradeByStuIdAndCourseId(courseId, studentId);
        if (studentGradeDtos == null) {
            res.put("msg", "获取参数错误");
            log.error("/queryStuGrades查询为空 user:{} , data:{}", user, map);
            return Result.error(res);
        }
        log.info("/queryStuGrades查询结果为 res:{}", studentGradeDtos);
        res.put("data", studentGradeDtos);
        return Result.success(res);
    }

    @PostMapping("/getReportByStuIdAndExperId")
    public Result getReportByStuIdAndExperId(HttpServletRequest request, @RequestBody HashMap<String, String> map) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            return Result.unauthorized();
        }
        log.info("/getReportByStuIdAndExperId: user:" + user.getUsername() + ", experId=" + map.get("experId"));
        String stuId = user.getUserId();
        Report report = reportService.getReportByStudentIdExperimentId(stuId, map.get("experId"));
        res.put("report", report);
        res.put("msg", "获取报告信息成功");
        return Result.success(res);
    }

    /**
     * 学生查询成绩，根据课程id和学生id
     * @param request
     * @param map
     * @return
     */
    @PostMapping("/getReportScoreByStuIdAndCourseId")
    public Result getReportScoreByStuIdAndCourseId(HttpServletRequest request, @RequestBody HashMap<String, String> map) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            return Result.unauthorized();
        }
        log.info("/getReportScoreByStuIdAndCourseId: user:" + user.getUsername() + ", courseId=" + map.get("courseId"));
        String stuId = user.getUserId();
        List<ScoreVO> scoreList = reportService.getReportScoreByStuIdAndCourseId(stuId, map.get("courseId"));
        res.put("scoreList", scoreList);
        res.put("msg", "获取报告信息成功");
        return Result.success(res);
    }

    @PostMapping("/getReportInfoByStuIdAndExperId")
    public Result getReportInfoByStuIdAndExperId(HttpServletRequest request, @RequestBody HashMap<String, String> map) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            return Result.unauthorized();
        }
        String stuId = user.getUserId();
        String experId = map.get("experId");
        ReportInfo reportInfo = studentMapper.getReportInfoByStuIdAndExperId(stuId, experId);
        res.put("reportInfo", reportInfo);
        return Result.success(res);
    }

    /**
     * 学生上传实验报告
     *
     * @param request 用户
     * @param file    文件
     * @return isSuccess
     */
    @PostMapping("/stuUploadReport")
    public Result<JSONObject> stuUploadReport(HttpServletRequest request, Report report,
                                              MultipartFile file) throws UnsupportedEncodingException {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            return Result.unauthorized();
        }
        log.info("/stuUploadReport收到: user{} , experId={}", user, report.getExperId());
        String stuId = user.getUserId();
        Boolean flag;
        String status = String.valueOf(report.getStatus());
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (status.equals("2")) {
            // delete old file
            Report oldReport = reportService.getReportByStudentIdExperimentId(stuId, report.getExperId());
            String fileName = oldReport.getReportFile();
            if (fileName != null) {
                MinIoUtil.deleteFile(minioProperties.getBucketName(), StringParseUtil.getFileNameFromUrl(fileName));
            }
            // update
            String fileUrl = MinIoUtil.upload(minioProperties.getBucketName(), file, stuId);
            report.setReportFile(fileUrl);
            report.setStatus(2);
            report.setReportTime(sdf.format(now));
            flag = reportService.stuUpdateReportFile(report);
            if (flag) {
                res.put("msg", "实验报告更新成功");
            }
        } else {
            // insert
            String fileUrl = MinIoUtil.upload(minioProperties.getBucketName(), file, stuId);
            report.setReportFile(fileUrl);
            report.setStatus(2);
            report.setReportTime(sdf.format(now));
            flag = reportService.saveOrUpdate(report);
            if (flag) {
                res.put("msg", "上传实验报告成功");
            }
        }
        return Result.success(res);
    }

    /**
     * 教师批改报告，为报告添加评分和评语
     *
     * @param request r
     * @param report  r
     * @return msg
     */
    @PostMapping("/markReport")
    public Result<JSONObject> markReport(HttpServletRequest request, @RequestBody Report report) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            return Result.unauthorized();
        }
        log.info("/markReport接收请求 user:" + user.getUsername() + "reportId:" + report.getId());
        try {
            Boolean flag = reportService.markReport(report);
            if (flag) {
                res.put("msg", "报告批阅成功");
                log.info("报告批阅成功");
                return Result.success(res);
            } else {
                res.put("msg", "报告批阅出错");
                log.info("报告批阅出错");
                return Result.error(res);
            }
        } catch (Exception e) {
            e.printStackTrace();
            res.put("msg", "报告批阅出错");
            return Result.error(res);
        }

    }

    /**
     * 教师批改报告，为报告添加评分和评语
     *
     * @param request r
     * @param report  r
     * @return msg
     */
    @PostMapping("/getMarkedInfo")
    public Result<JSONObject> getMarkedInfo(HttpServletRequest request, @RequestBody Report report) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            return Result.unauthorized();
        }
        log.info("/getMarkedInfo接收请求 user:" + user.getUsername() + "reportId:" + report.getId());
        try {
            Report reportInfo = reportService.getMarkedInfo(report);
            if (reportInfo != null) {
                res.put("msg", "获取报告信息成功");
                res.put("reportInfo", reportInfo);
                log.info("获取报告信息成功");
                return Result.success(res);
            } else {
                res.put("msg", "获取报告信息出错");
                log.info("获取报告信息出错");
                return Result.error(res);
            }
        } catch (Exception e) {
            e.printStackTrace();
            res.put("msg", "获取报告信息出错");
            return Result.error(res);
        }

    }

    @PostMapping("/getExperScoreByStuId")
    public Result<JSONObject> getExperScoreByStuId(HttpServletRequest request) {
        JSONObject res = new JSONObject();
        String token = request.getHeader("Authorization");
        RUser user = redisUtil.getUser(token);
        if (user == null) {
            return Result.unauthorized();
        }
        String stuId = user.getUserId();
        log.info("/getExperScoreByStuId接收请求 user:" + user.getUsername());
        return Result.success(res);
    }
}
